package com.test45_JUC;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * DelayQueue，延迟队列
 * 延迟队列最大的特点在于，如果时间到了，则会自动的弹出数据。
 * 阻塞队列是需要开发者通过线程的操作获取队列的内容，但是延迟队列是可以自己进行数据弹出的，
 * 延迟队列使用的时候我们开发者只能够接收弹出的数据项。
 */
public class Demo23_DelayQueue {

    public static void main(String[] args) throws Exception {
        test1();
    }

    /**
     * 实现延迟队列自动弹出
     */
    public static void test1() throws Exception {
        BlockingQueue<Employee> queue = new DelayQueue<>();
        queue.put(new Employee("小李老师", "图书编写创作", 5, TimeUnit.SECONDS));
        queue.put(new Employee("小张老师", "视频后期剪辑", 2, TimeUnit.SECONDS));
        queue.put(new Employee("小王老师", "少儿编程课程", 6, TimeUnit.SECONDS));
        // 所有的延迟队列到点之后可以自动的弹出，那么下面就需要等待这些弹出的数据内容
        while (!queue.isEmpty()) {
            Employee employee = queue.take();   // 获取超时的数据
            System.out.println(employee);
            TimeUnit.SECONDS.sleep(1);
        }
    }
}

/**
 * 定义延迟队列项
 */
class Employee implements Delayed {

    private String name;    // 雇员姓名

    private String task;    // 雇员任务

    private long start = System.currentTimeMillis();

    private long delay;     // 延迟的时间

    // 传入的时间单元可能是秒、分，但是最终存储的时候一定是毫秒，这里面就需要进行转换
    public Employee(String name, String task, long delay, TimeUnit timeUnit) {
        this.name = name;
        this.task = task;
        this.delay = TimeUnit.MILLISECONDS.convert(delay, timeUnit);
    }

    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert((this.start + this.delay)
                - System.currentTimeMillis(), TimeUnit.MILLISECONDS);   // 延迟的计算
    }

    @Override
    public int compareTo(Delayed o) {   // 延迟队列的内部存在优先级队列
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }

    @Override
    public String toString() {
        return "【任务完成】雇员“" + this.name + "”，完成了“" + this.task + "”工作，一共花费了“" + this.delay + "”毫秒的时间";
    }
}